using UnityEngine;
using System.Collections;

/**
 * Script of controller behaviour description.
 * The purpose of this class is to catch and control key pushes.
 * @author Benjamin Bruneau
 */
public class ControllerScript : MonoBehaviour 
{
	private const string BALL_NAME = "Ball"; // Main GameObject's name
	private const string PAUSE_MANAGER_NAME = "PauseManager"; // PauseManager GameObject
	
	public float _maxAltModifier = 2.0f; //Max acceleration
	public float _resetAltModifier = 0f; //Min acceleration
	public float _acceleration = 0.1f; //Acceleration rate
	
	public bool _enabled; //Activation of the stage
	public bool _bumper = false; //Up and down control
	public bool _verticalBlocked = false; //Block up and down control
	
	public GameObject _lastLevel; //Last stage
	public GameObject _dataContainer; // Data Container
	
		
	/**
	 * Called once per frame.
	 * @return void
	 */
	void Update ()
	{
		// If this stage is activated (and shall move witih controls)
		if (_enabled) 
		{
			release();
			resetLevel();
		}
	}
	
	/**
	 * Called once per fixed frame.
	 * @return void
	 */
	void FixedUpdate ()
	{
		// If this stage is activated (and shall move witih controls)
		if (_enabled) 
		{
			control ();
		}
	}
	
	/*
	 * Called on collision.
	 * @param Collision
	 * @return void
	 */
	void OnCollisionEnter(Collision pCollision)
	{
		// On ball collision
		if (pCollision.gameObject.name.Equals(BALL_NAME))
		{
			//Destroys last stage (useless and free memory)
			if(_lastLevel != null)
		DestroyObject(_lastLevel);
		//Enables player to control current stage
		_enabled = true;
		}	
	}
	
	/**
	 * Called to reset acceleration on key release.
	 * @return void
	 */ 
	private void release ()
	{
		//On release
		if (Input.GetKeyUp(KeyCode.LeftArrow) || Input.GetKeyUp(KeyCode.RightArrow) || Input.GetKeyUp(KeyCode.UpArrow) || Input.GetKeyUp(KeyCode.DownArrow))
		{
			//Reset stage's rotation speed and acceleration
			_dataContainer.GetComponent<DataContainerScript>()._altModifier = _resetAltModifier;
		}
	}
	
	/**
	 * Called to reset current level when pressing R.
	 * @return void
	 */ 
	private void resetLevel ()
	{
		//Reset
		if (Input.GetKeyUp(KeyCode.R))
		{
			GameObject pauseManager = GameObject.Find(PAUSE_MANAGER_NAME);
			
			if(pauseManager != null)
			{
				if(!pauseManager.GetComponent<PauseControllerScript>()._pause)
				{
					
					string currentLevel = _dataContainer.GetComponent<DataContainerScript>()._currentLevel;
			
					//Result Destroyer (persistent)
					Destroy(_dataContainer);
					Application.LoadLevel(currentLevel);
					
				} 
			} else {
				
				string currentLevel = _dataContainer.GetComponent<DataContainerScript>()._currentLevel;
			
				//Result Destroyer (persistent)
				Destroy(_dataContainer);
				Application.LoadLevel(currentLevel);
			}	
		}
	}
		
	/**
	 * Called to check and use key pushes.
	 * @return void
	 */ 
	private void control(){
		
		//On press
		controllerMovement(KeyCode.LeftArrow,Vector3.left);
		controllerMovement(KeyCode.RightArrow,Vector3.right);
		
		// If Vertical movement unlocked
		if (!_verticalBlocked)
		{
			if (!_bumper)
			{
				//Classic controls
				controllerMovement(KeyCode.UpArrow,Vector3.forward);
				controllerMovement(KeyCode.DownArrow,Vector3.back);
			} else {
				// Lift control
				controllerMovementBump(KeyCode.UpArrow,Vector3.up);
				controllerMovementBump(KeyCode.DownArrow,Vector3.down);
			}
		}
	}
	
	/**
	 * Called to rotate the current stage (on key demand).
	 * @param KeyCode, Vector3
	 * @return void
	 */
	private void controllerMovement(KeyCode pKeyCode, Vector3 pVector3)
	{
		if (Input.GetKey(pKeyCode))
		{
			transform.Rotate(pVector3*_dataContainer.GetComponent<DataContainerScript>()._altModifier * Time.deltaTime);		
			alterationIncrementation ();
		}
	}
	
	/**
	 * Called to lift the current stage (on key demand).
	 * @param KeyCode, Vector3
	 * @return void
	 */
	private void controllerMovementBump(KeyCode pKeyCode, Vector3 pVector3)
	{
		if (Input.GetKey(pKeyCode))
		{
			transform.Translate(pVector3*_dataContainer.GetComponent<DataContainerScript>()._altModifier * Time.deltaTime);		
			alterationIncrementation ();
		}
	}
	
	/**
	 * Called to update acceleration rate.
	 * @return void
	 */
	private void alterationIncrementation ()
	{
		if (_dataContainer.GetComponent<DataContainerScript>()._altModifier < _maxAltModifier)
		{
			_dataContainer.GetComponent<DataContainerScript>()._altModifier += _acceleration / _dataContainer.GetComponent<DataContainerScript>()._countActivatedStages;
		}
	}
}
